import pygame
import object
import math

pi          = 3.141592653
max_angle   = 5*pi/12 
max_magnitude   = 1.5
min_magnitude   = 0.5

class Ball(object.Object):
    def __init__(self, position_x, position_y):
        super(Ball, self).__init__(position_x, position_y)
        self.magnitude = 0
        self.max_speed = 5.0

    def __init__(self, position_x, position_y, speed_y):
        super(Ball, self).__init__(position_x, position_y, speed_x, speed_y)
        self.magnitude = 0
        self.max_speed = 5.0

    def __init__(self, position_x, position_y, speed_x, speed_y, width, height):
        super(Ball, self).__init__(position_x, position_y, speed_x, speed_y, width, height)
        self.magnitude = 0
        self.max_speed = 5.0

    def getRect(self):
        return pygame.rect.Rect(object.Object.getRect(self))

    # Polar representation of speed vector
    def to_polar(self):
        self.magnitude = math.sqrt( \
            self.speed_x*self.speed_x + self.speed_y*self.speed_y)
        self.angle = math.atan2(self.speed_y, self.speed_x)

    # Cartesian representation of speed vector
    def to_cart(self):
        self.speed_x = self.magnitude * math.cos(self.angle)
        self.speed_y = self.magnitude * math.sin(self.angle)

    # Rect is the object against which the ball bounces
    #~ rect = [x, y, width, height]
    def collision_up(self, rect):
        rect = pygame.Rect(rect)
        collision = False
        if self.position_y <= (rect.top + rect.height):
            collision = True
        return collision

    def collision_down(self, rect):
        rect = pygame.Rect(rect)
        collision = False
        if (self.position_y + self.height) >= rect.top:
            collision = True
        return collision

    def collision_left(self, rect):		
        rect = pygame.Rect(rect)
        collision = False
        if (self.position_x <= (rect.left + rect.width)) and \
                (self.position_y > rect.top) and                  \
                (self.position_y < (rect.top + rect.height)):
                    collision = True
        return collision

    def collision_right(self, rect):		
        rect = pygame.Rect(rect)
        collision = False
        if ((self.position_x + self.width) >= rect.left) and \
                (self.position_y > rect.top) and                 \
                (self.position_y < (rect.top + rect.height)):
                    collision = True
        return collision

    def bounce_x(self):
        self.speed_x *= -1

    def bounce_y(self):
        # Avoid endless bouncing 
        self.speed_y += 0.2        
        self.speed_y *= -1        

    # Change angle according to distance to center of the paddle
    # TODO: Doesn't work
    def bounce_paddle(self, paddle ):
		#~ self.bounce_x()
		#~ self.speed_y += float((paddle.bottom + paddle.height) / 2.0 - self.position_y)/float(paddle.height/2.0);
        distance = (paddle.bottom + paddle.height / 2.0) - self.position_y;
        # Normalize
        distance /= paddle.height/2.0;
        #~ self.to_polar()
        self.angle = distance * max_angle;
        # If it's the left paddle reverse the angle
        if self.speed_x < 0:
            self.angle += pi		
        
        self.magnitude = distance * max_magnitude + min_magnitude
        self.to_cart()

    def bounce_paddle_simple(self, paddle ):
		self.bounce_x()
		pos_bounce = (paddle.top + paddle.height / 2.0) - self.position_y
		block_size = paddle.height / 4.0
		blocks = [-2*block_size, -block_size, 0.0, block_size, 2*block_size]
		
		
		self.speed_y = abs(self.speed_y)
		if blocks[0] <= pos_bounce < blocks[1]:
			self.speed_y *= 1.2
		elif blocks[1] <= pos_bounce < blocks[2]:
			self.speed_y *= 1.0
		elif blocks[2] <= pos_bounce < blocks[3]:
			self.speed_y *= -1.0
		elif blocks[3] <= pos_bounce <= blocks[4]:
			self.speed_y *= -1.2
		else:
			print "ERR"
	
		if abs(self.speed_y) > self.max_speed:
			self.speed_y *=0.8


    def update(self, rect1, rect2):
        self.updatePosition()
        # Check for losses
        rect = self.getLimits() # x, y, width, height
        
        rect_left = [rect[0], rect[1], 0, rect[3]]        
        if self.collision_left(rect_left):
            print("Player 1 loses a life")
            return [True, 1]

        rect_right = [rect[0] + rect[2], rect[1], 0, rect[3]]
        if self.collision_right(rect_right):
            print("Player 2 loses a life")
            return [True, 2]

        # Bounce against wall
        rect_up = [rect[0], rect[1], rect[2], 0]  
        if self.collision_up(rect_up):            
            print("Bounce against upper wall")
            self.bounce_y()

        rect_down = [rect[0], rect[1] + rect[3], rect[2], 0]   
        if self.collision_down(rect_down):
            print("Bounce against lower wall")
            self.bounce_y()
        
        # Bounce against first player paddle            
        if self.getRect().colliderect(rect1):
            while(self.getRect().colliderect(rect1)):
                    self.position_x+=1
            print("Bounce against first paddle")
            self.bounce_paddle_simple(rect1)               

        # Bounce against second player paddle
        if self.getRect().colliderect(rect2):
            while(self.getRect().colliderect(rect2)):
                    self.position_x-=1
            print("Bounce against second paddle")
            self.bounce_paddle_simple(rect2)


        self.updatePosition()

        return [False, 0]
